/**
 * 作者：陈文斌 on 2018/12/27.
 * 邮箱：chen_wennbin@163.com
 * 版本：v1.0
 */

import 'dart:io';
import 'dart:convert';
import 'package:path/path.dart';
import 'package:async/async.dart';
import 'package:http/http.dart' as http;
import 'shared_preferences_util.dart';
import 'package:crm/constant/api.dart';

class HttpUtil {
  static const String GET = "get";
  static const String POST = "post";

  // GET请求
  static void get(
    String url,
    Function callback, {
    Map<String, String> params,
    Map<String, String> headers,
    Function errorCallback,
    bool isSaveCookie = true,
  }) async {
    if (!url.startsWith("http")) {
      url = Api.BaseUrl + url;
    }

    if (params != null && params.isNotEmpty) {
      // 参数拼接
      StringBuffer sb = new StringBuffer("?");
      params.forEach((key, value) {
        sb.write("$key" + "=" + "$value" + "&");
      });
      String paramStr = sb.toString();
      paramStr = paramStr.substring(0, paramStr.length - 1);
      url += paramStr;
    }
    await _request(
      url,
      callback,
      method: GET,
      headers: headers,
      errorCallback: errorCallback,
      isSaveCookie: isSaveCookie,
    );
  }

  //POST请求
  static void post(
    String url,
    Function callback, {
    params,
    Map<String, String> headers,
    Function errorCallback,
    bool isSaveCookie = true,
  }) async {
    if (!url.startsWith("http")) {
      url = Api.BaseUrl + url;
    }
    await _request(
      url,
      callback,
      method: POST,
      headers: headers,
      params: params,
      errorCallback: errorCallback,
      isSaveCookie: isSaveCookie,
    );
  }

  // multipart/form-data提交
  static void multipartRequest(
    String url,
    Function callback, {
    params,
    Map<String, String> headers,
    Function errorCallback,
    bool isSaveCookie = true,
  }) {
    Map<String, String> headerMap = headers == null ? new Map() : headers;
    var paramMap = params == null ? new Map() : params;

    var multipartRequest = http.MultipartRequest("POST", Uri.parse(url));
    paramMap.forEach((key, value) {
      multipartRequest.fields[key] = json.encoder.convert(value);
    });

    headerMap.forEach((key, value) {
      multipartRequest.headers[key] = json.encoder.convert(value);
    });

    if (SpUtil.getString('Cookies') != null) {
      multipartRequest.headers['Cookie'] = SpUtil.getString('Cookies');
    }
    print('cookie=>${multipartRequest.headers}');

    multipartRequest.send().then((http.StreamedResponse r) {
      print('${r.request.url} ,method=${r.request.method}');
      print('请求参数：${jsonEncode(paramMap)}');
      _multipartDataDetection(
        r,
        callback,
        errorCallback,
        isSaveCookie,
      );
    });
  }

  // 文件提交
  static void multipartFile(
    String url,
    Function callback, {
    File file,
    params,
    Map<String, String> headers,
    Function errorCallback,
    bool isSaveCookie = true,
  }) async {
    var multipartRequest = new http.MultipartRequest("POST", Uri.parse(url));

    if (file != null) {
      var stream = new http.ByteStream(DelegatingStream.typed(file.openRead()));
      var length = await file.length();

      var multipartFile = new http.MultipartFile('files', stream, length,
          filename: basename(file.path));

      multipartRequest.files.add(multipartFile);
    }

    Map<String, String> headerMap = headers == null ? new Map() : headers;
    var paramMap = params == null ? new Map() : params;

    paramMap.forEach((key, value) {
      multipartRequest.fields[key] = value;
    });

    headerMap.forEach((key, value) {
      multipartRequest.headers[key] = json.encoder.convert(value);
    });

    if (SpUtil.getString('Cookies') != null) {
      multipartRequest.headers['Cookie'] = SpUtil.getString('Cookies');
    }
    multipartRequest.send().then((http.StreamedResponse r) {
      print('${r.request.url} ,method=${r.request.method}');
      print('请求参数：${jsonEncode(paramMap)}');
      _multipartDataDetection(r, callback, errorCallback, isSaveCookie);
    });
  }

  static Future _request(
    String url,
    Function callback, {
    String method,
    Map<String, String> headers,
    params,
    Function errorCallback,
    bool isSaveCookie,
  }) async {
    try {
      Map<String, String> headerMap = headers == null ? new Map() : headers;
      var paramMap = params == null ? new Map() : params;

      headerMap['Content-type'] = 'application/json';

      if (SpUtil.getString('Cookies') != null) {
        headerMap['Cookie'] = SpUtil.getString('Cookies');
      }

      var client = new http.Client();
      if (POST == method) {
        client
            .post(
          Uri.parse(url),
          headers: headerMap,
          body: json.encoder.convert(paramMap),
        )
            .then((http.Response r) {
          print('${r.request.url} ,method=${r.request.method}');
          if (r.request.method == 'POST') {
            print('请求参数：${jsonEncode(paramMap)}');
          }
          print('响应内容:code=${r.statusCode} size=${r.contentLength},${r.body}');
          _dataDetection(r, callback, errorCallback, isSaveCookie);
        });
      } else {
        client.get(Uri.parse(url), headers: headerMap).then((http.Response r) {
          _dataDetection(r, callback, errorCallback, isSaveCookie);
        });
      }
    } catch (exception) {
      _handError(errorCallback, exception.toString());
    }
  }

  static void _dataDetection(
    http.Response r,
    callback,
    errorCallback,
    bool isSaveCookie,
  ) {
    if (r.statusCode != 200) {
      if (jsonDecode(r.body) is Map) {
        _handError(errorCallback, jsonDecode(r.body)['Message']);
      } else {
        _handError(errorCallback, jsonDecode(r.body));
      }

      return;
    }

    // 请求成功

    // cookies处理
    if (isSaveCookie) {
      String cookies = r.headers['set-cookie'];
      if (cookies != null) {
        SpUtil.putString('Cookies', cookies);
      }
      if (callback != null) {
        callback(json.decoder.convert(utf8.decoder.convert(r.bodyBytes)));
      }
    }
  }

  static void _multipartDataDetection(
    http.StreamedResponse r,
    callback,
    errorCallback,
    bool isSaveCookie,
  ) {
    r.stream.bytesToString().then(
      (body) {
        print('响应内容:code=${r.statusCode} size=${r.contentLength},${body}');

        if (r.statusCode == 200) {
          if (isSaveCookie) {
            // cookies处理
            String cookies = r.headers['set-cookie'];
            if (cookies != null) {
              SpUtil.putString('Cookies', cookies);
            }
          }
          if (callback != null) {
            callback(json.decoder.convert(body));
          }

          return;
        }

        if (r.statusCode == 403) {
          _handError(errorCallback, '未授权');

          return;
        }

        r.stream.bytesToString().then((body) {
          if (jsonDecode(body) is Map) {
            _handError(errorCallback, jsonDecode(body)['Message']);
          } else {
            _handError(errorCallback, jsonDecode(body));
          }
        });
      },
    );
  }

  static void _handError(Function errorCallback, String errorMsg) {
    if (errorCallback != null) {
      errorCallback(errorMsg);
    }
  }
}
